Feed repo conventions (AGENTS.md/CLAUDE.md) to the review engine - #5
Conversation
…he engine Point the review engine at the repo's own AGENTS.md/CLAUDE.md/CONTRIBUTING.md so it stops flagging deliberate project choices as issues. The directive rides --background and is gated to same-repo PRs only: a fork's head-checked-out conventions doc is attacker-controlled, so the directive (which tells the engine to trust that file) must never apply to forks. Framed defensively — the doc is untrusted reference data that may only suppress style findings and can never weaken correctness/security review or alter severity tagging. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b0325ee83a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| # conventions doc is attacker-controlled, and the directive tells the | ||
| # engine to trust that file. Rides --background (well under the engine's | ||
| # cap; the directive is short and never inlines the conventions doc). | ||
| if [ "$SAME_REPO" = "true" ] && [ -s "$CONVENTIONS_DIRECTIVE" ]; then |
There was a problem hiding this comment.
Do not trust convention files from same-repo PR heads
When contributors can push feature branches in the base repository but still need PR approval, same_repo is true even though the PR can add or modify its root AGENTS.md/CLAUDE.md. The action checks out that unreviewed head SHA (action.yml:417) before the engine follows this directive, so such a PR can inject instructions into the model context to suppress correctness or security findings; describing the file as “untrusted data” in another prompt does not prevent the model from interpreting its contents as instructions. Restrict convention lookup to the protected base revision, or do not load PR-head convention files at all.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
The conventions directive pointed the engine at the PR head's AGENTS.md/CLAUDE.md, which a fork PR author controls (Codex P1). Extract the doc ourselves from the trusted base revision via `git show "$BASE:<path>"` and inline it into the background, dropping the same_repo gate (base is trusted regardless of fork). Switch the invocation to --background-file so a large doc can't hit the argv limit. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
…nd-file) The pinned engine 1.3.13 errors on --background-file (that flag only exists in newer versions). Pass the assembled background file inline via --background "$(cat …)", which 1.3.13 supports; the base-revision conventions extraction is unchanged. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
There was a problem hiding this comment.
🐳 Orca-Code-Review
Found 2 issues in this PR: 🟡 2 P2.
Reviewed via OrcaRouter — Route Smarter. Ship Safer. Spend Less.
| printf '\n\n----- BEGIN %s (untrusted project conventions; read-only reference) -----\n' "$f" | ||
| printf '%s\n' "$doc" | ||
| printf -- '----- END %s -----\n' "$f" | ||
| } >> "$BACKGROUND" |
There was a problem hiding this comment.
🟡 P2 If a base-revision conventions file is unusually large, this appends it unbounded into BACKGROUND, which is later expanded inline via --background "$(cat "$BACKGROUND")"; that can exceed the OS argv limit and fail the action before review results are produced. Cap or truncate the appended conventions content to a safe size before inlining.
| // after the untrusted-data framing. | ||
| assert.match(yml, /--background "\$\(cat "\$BACKGROUND"\)"/, "must pass the background inline (1.3.13 has no --background-file)"); | ||
| assert.doesNotMatch(yml, /--background-file "/, "must not invoke the unsupported --background-file flag"); | ||
| assert.match(yml, /cat "\$CONVENTIONS_DIRECTIVE"/, "the framing directive must precede the inlined doc"); |
There was a problem hiding this comment.
🟡 P2 This assertion only proves the directive text appears somewhere in action.yml; it does not verify that the directive is appended before the base-revision document. If the shell block is later reordered so the untrusted conventions are written before the framing directive, this security test would still pass as long as both snippets remain present. Consider asserting the relative order (for example, locate cat "$CONVENTIONS_DIRECTIVE" and ensure it precedes the printf '%s\n' "$doc" append within the same block).
There was a problem hiding this comment.
💡 Codex Review
Lines 690 to 692 in e8a4df7
When the first available root convention file is larger than Linux's per-argument limit (roughly 128 KiB), such as a substantial CONTRIBUTING.md, command substitution makes the --background value too large and ocr fails with Argument list too long before any review runs. The action accepts CONTRIBUTING.md without a size bound and only has an inline-background path, so truncate/skip oversized convention files (or upgrade to a file-based engine interface) rather than turning these otherwise valid PR reviews into failed checks.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Only inline the base-revision conventions doc when the PR targets the repo's default branch — a PR base is author-chosen, so only the default branch is a protected ref the author cannot rewrite. Cap the appended doc at 32 KiB to keep the inline --background argv under E2BIG, and pin the framing-directive-before-doc order in the test. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
There was a problem hiding this comment.
🐳 Orca-Code-Review
Found 1 issue in this PR: ⚪ 1 P3.
Reviewed via OrcaRouter — Route Smarter. Ship Safer. Spend Less.
| // by the PR) via `git show "$BASE:<path>"` and inlines it into the background | ||
| // file, framed as untrusted data that can never weaken the review or change | ||
| // severity tags. Size is safe because we pass --background-file (a path), not | ||
| // an inline --background argv value. |
There was a problem hiding this comment.
⚪ P3 This comment is now inconsistent with the assertions below and the current workflow: the background is passed inline via --background "$(cat "$BACKGROUND")", not via --background-file. That can mislead future changes to this security-sensitive wiring and the argv-size cap rationale.
Orca-Code-Review — push 3
Tier: STRONG (final pass) — pass
✅ no blocking findings
Summary
AGENTS.md/CLAUDE.md/CONTRIBUTING.mdto learn project-specific conventions, so it stops flagging deliberate project choices as findings (a precision win toward the Codex bar).--background(additive — the built-in language/security review and our severity contract are untouched). The conventions doc itself is never inlined into--background; the agent reads it via its file tools, so there's no cap pressure.same_repooutput on theprstep (head vs. base repo identity; a deleted-fork nullhead.repocounts as not-same-repo).[P0]/[P1]/[P2]/[P3]tags the whole pipeline greps.Changes
action.yml:prstep emitssame_repo; review step appends the directive to--backgroundonly whenSAME_REPO == true.rules/conventions-directive.md: the directive text (new).scripts/conventions-directive.test.mjs: pins the fork-injection gate and the defensive framing so a refactor can't silently drop them.Test plan
node --test scripts/conventions-directive.test.mjs— 3/3 pass (same_repo derivation, SAME_REPO gate on the concat, untrusted/severity-preserving framing).action.ymlparses as valid YAML.🤖 Generated with Claude Code